#ifndef TCP_SERVER_H_
#define TCP_SERVER_H_
#define MAX 64
#define LISTENQ 5

#define DEGBUG 1
#if DEGBUG
#define LOG(s) cout<<s<<endl;
#else
#define LOG(s) /*Comment*/
#endif
#include<fstream>
#include<iostream>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<netinet/in.h>
#include<fcntl.h>
#include<string.h>
#include<sys/stat.h>

using namespace std;

class TCP_Server
{
	int listenfd, connfd;
	struct sockaddr_in servaddr, cliaddr;
	socklen_t clilen;
	char  inputfile[MAX];			//Uncompressed File
	char outputfile[MAX];			//Compressed .rir file to be sent to the client
	char buf[MAX];

	int ProcessRequest();
	int Compress();
public :
	TCP_Server(int port_number);
	int Socket();
	int Bind();
	int Listen();
	int Accept();
	int SendCompressedFile();
	int DisplayFile();

	~TCP_Server();
};

TCP_Server::~TCP_Server(){ LOG(__func__);}
TCP_Server::TCP_Server(const int port_number)
{
	LOG(__func__);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(port_number);
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

}
int TCP_Server::Socket()
{
	LOG(__func__);
	return (listenfd = socket(AF_INET, SOCK_STREAM, 0));
}
int TCP_Server::Bind()
{
	LOG(__func__);
	return bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
}
int TCP_Server::Listen()
{
	LOG(__func__);
	return listen(listenfd, LISTENQ);
}

int TCP_Server::Accept()
{
	LOG(__func__);
	pid_t childpid;
	while(1)
	{
		clilen = sizeof(cliaddr);
		connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
		if((childpid = fork()) == 0)
		{
			close(listenfd);
			ProcessRequest();
			exit(0);
		}
		close(connfd);
	}
}
int TCP_Server::SendCompressedFile()
{
	LOG(__func__);
	
	

	cout << endl << "Output File ==== " << outputfile << endl << endl;

	int fd = open(outputfile, O_RDONLY);
	int n;
	while((n = read(fd, buf, sizeof(buf))) > 0)
	{
		write(connfd, buf, n);
		cout << "\nn = " << n << endl;
		//write(STDOUT_FILENO, buf, n);
	}
	close(fd);
	

}
int TCP_Server::ProcessRequest()
{
	LOG(__func__);
	int n;
	n = read(connfd, buf, sizeof(buf)); //read the name of the file.
	buf[n] = '\0';   //null terminate
	strcpy(inputfile, buf);
	strcpy(outputfile,inputfile);
	strcat(outputfile, ".rir");

	cout << "\nOutput filename = " << outputfile << endl;	
	
	Compress();
	SendCompressedFile();

	unlink(outputfile); //delete the compressed file at the server side after sending it to the client.

}

int TCP_Server::Compress()
{
	LOG(__func__);
	pid_t childpid;
	int status;
	childpid = fork();
	if(childpid == 0)
	{
		execl("/home/nsatvik/Projects/DC_Project/DCP-v8.0/Server/huff","Compressor", inputfile, outputfile, (char*) NULL);
		//execlp("huff","Compressor", inputfile, outputfile, (char *)0);


	}
	if(waitpid(childpid, &status, 0) == -1)
	{
		perror("Waitpid:");
		exit(1);
	}
	cout<<"Compression Over!... Sending the file "<<inputfile<<endl;
	return 1;
}
int TCP_Server::DisplayFile()
{
	LOG(__func__);
	ifstream in;
	in.open(outputfile);
	char ch;
	while((ch = in.get()) != EOF)
	{
		cout<<ch;
	}
	in.close();
}

#endif /* TCP_SERVER_H_ */
